#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <vector>
#include "wave_atom.h"

using namespace std;

int Write(const Wave & wave, long max, long min, int repeat = 1)
{
	vector<double> d_tbl = wave.MakeWaveTable(repeat, 1.0, -1.0);
	vector<long> l_tbl(d_tbl.size());

	long range = max - min;
	for(int i = 0; i < d_tbl.size(); ++i)
	{
		l_tbl[i] = (long) (d_tbl[i] * range * 0.5 + 0.5) ;
	}

	cout << "//freq: " << wave.GetFreq() << " Hz, repeat: "
			<< repeat << " times, samplerate: " << wave.GetSampleRate()
			<<", total " << d_tbl.size() <<" samples" <<endl;
	cout << "long "<<wave.GetName() <<" [] = {" << endl;
	cout << "\t";
	int count=0;
	for(int i=0; i<d_tbl.size(); ++i)
	{
		cout<<setw(11)<<setprecision(8)<<hex<<showbase<<uppercase<<l_tbl[i]<<",";
		++count;
		if(count == 5)
		{
			count=0;
			cout<<endl<<"\t";
		}
	}
	cout<<endl;
	cout<<"};"<<endl;
	cout<<dec<<noshowbase<<nouppercase<<endl;
    return d_tbl.size();
}

int main(int argc, char *argv[])
{
	if(argc < 3)
	{
		cerr << "command SAMPLE_RATE FREQ_FILE [OPTIONAL to gen more info]" <<endl;
		exit(0);
	}

	double sampleRate = atof(argv[1]);
	ifstream freqFile(argv[2]);
	if(!freqFile)
	{
		cerr << "Cannot Open freqFile: "<<argv[2]<<endl;
		exit(0);
	}

	char buf[1024];
	freqFile.getline(buf,1024);

	int wheelNum;
	freqFile >> wheelNum;

	vector<double> freqList(wheelNum);
	for(int i = 0; i<wheelNum; ++i)
	{
		freqFile >> freqList[i];
	}
	freqFile.close();

    vector<string> nameList(wheelNum);
    vector<int> lenList(wheelNum);

	cout << "#ifndef KK_B3_WAVETABLE_H" <<endl;
	cout << "#define KK_B3_WAVETABLE_H" <<endl;
	cout << endl;

	if(argc == 4)
	{
        cout << "#ifdef __cplusplus" <<endl;
        cout << "#include <cstdlib>" <<endl;
        cout << "#else" <<endl;
        cout << "#include <stdlib.h>" <<endl;
        cout << "#endif" <<endl;
        cout << endl;
	}
	cout << "// " << buf <<endl;
	cout << endl;

	for(int i = 0; i < wheelNum; ++i)
	{
		string name = string("wheel_") + char( (i+1)/10 + '0') + char( (i+1)%10+'0') ;
		AlignedSine sine(freqList[i], sampleRate, false, 0.1, name);

		//Dynamic adjust of search range, lowest: 1/thres, highest: 10/thres.
		int maxLoop = int ( 500 / ( sampleRate / freqList[i] ) + 1 );
		if (maxLoop < 1)
			maxLoop = 1;

		bool suc = sine.Align(1, maxLoop, false);
		while ( !suc )
		{
			maxLoop *= 2;
			suc = sine.Align(1, maxLoop);
		}

		int len = Write(sine, 0X7FFFFF, - 0X7FFFFF, sine.GetLoop());
		nameList[i]=name;
        lenList[i]=len;
	}

    if(argc == 4 )
    {
        cout << "int wheelNum = " << wheelNum << ";" <<endl;
        cout << "double sampleRate = " << sampleRate<<";"<<endl;
        cout << "long rangeMin = - 0X7FFFFF;" <<endl;
        cout << "long rangeMax = 0X7FFFFF;" <<endl;
        cout << "long rangeMid = 0;" <<endl;
        cout << "long * wheels[] = {" <<endl;
        cout << "\tNULL, " <<endl;
        for(int i = 0; i< wheelNum ; ++i)
        {
            cout << "\t" <<nameList[i] <<"," <<endl;
        }
        cout << "};" <<endl;
        cout <<endl;

        cout << "int lens[] = {" <<endl;
        cout << "\t0," <<endl;
        for(int i = 0; i < wheelNum; ++i )
        {
            cout << "\t" << lenList[i] <<"," <<endl;
        }
        cout << "};" <<endl;
        cout <<endl;
    }
	cout << "#endif" <<endl;

	return 0;
}

